/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2020 @ ShenZhen ,China
*******************************************************************************/
#include "RegExp.h"
#include "Tracer.h"
#include <stdlib.h>
#include <regex.h>

namespace libemb{
/**
 *  \brief  RegExp构造函数
 *  \param  none
 *  \return none
 */
RegExp::RegExp()
{
}

/**
 *  \brief  RegExp析构函数
 *  \param  none
 *  \return none
 */
RegExp::~RegExp()
{
}

/**
 *  \brief  正则表达式匹配
 *  \param  pattern 正则表达式
 *  \param  source 要匹配的字符串
 *  \return 成功返回true,失败返回false
 */
bool RegExp::match(const std::string& pattern,const std::string& source)
{
    std::string str;
    int pos;
    return match(pattern,source,str,pos);
}
/**
 *  \brief  正则表达式匹配
 *  \param  pattern 正则表达式
 *  \param  source 要匹配的字符串
 *  \param  result 匹配结果
 *  \return 成功返回true,失败返回false
 */
bool RegExp::match(const std::string& pattern,const std::string& source,std::string& result,int& pos)
{
    StringArray strArray;
    IntArray posArray;
    result.clear();
    bool rc = match(pattern,source,strArray,posArray,1);
    if (rc)
    {
        result = strArray[0];
        pos = posArray[0];
    }
    return rc;
}
/**
 *  \brief  正则表达式匹配
 *  \param  pattern 正则表达式
 *  \param  source 要匹配的字符串
 *  \param  strArray 匹配结果
 *  \param  posArray 匹配结果对应所在的位置
 *  \param  maxMatches 最多匹配个数
 *  \return 成功返回true,失败返回false
 */
bool RegExp::match(const std::string& pattern, const std::string& source,StringArray & strArray, IntArray & posArray,int maxMatches)
{
    bool isMatched = false;
    regex_t regex;
    if (maxMatches<=0)
    {
        maxMatches=1;
    }
    if (0!=regcomp(&regex,CSTR(pattern),REG_EXTENDED))
    {
        TRACE_ERR_CLASS("regex compile error!\n");
        return false;
    }
    strArray.clear();
    posArray.clear();
    char* pStr = (char*)CSTR(source);
    char* pStart = pStr;
    for(auto i=0; i<maxMatches; i++)
    {
        regmatch_t regmatch;
        int rc=regexec(&regex,pStr,1,&regmatch,0);
        if (rc==REG_NOMATCH)
        {
            break;
        }
        else if (rc<0)
        {
            TRACE_ERR_CLASS("regex execute error!\n");                                                                                                                                                    
            break;
        }
        else
        {
            isMatched = true;
            if (regmatch.rm_so!=-1)
            {
                std::string result=std::string(pStr).substr(regmatch.rm_so,regmatch.rm_eo-regmatch.rm_so);
                posArray.append((int)(pStr+regmatch.rm_so-pStart));
                strArray.append(result);
                pStr = pStr+regmatch.rm_eo;
            }
            else
            {
                break;
            }
        }
    }
    regfree(&regex);
    return isMatched;
}
}